package dmir.reaction.publico.graph.neo4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.LinkedList;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.graph.api.Attributes;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.UndirectedGraph;
import org.gephi.io.importer.api.Container;
import org.gephi.io.importer.api.ImportController;
import org.gephi.io.processor.plugin.DefaultProcessor;
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
import org.gephi.statistics.plugin.ClusteringCoefficient;
import org.gephi.statistics.plugin.Degree;
import org.gephi.statistics.plugin.EigenvectorCentrality;
import org.gephi.statistics.plugin.GraphDistance;
import org.gephi.statistics.plugin.Hits;
import org.gephi.statistics.plugin.PageRank;
import org.neo4j.helpers.collection.MapUtil;
import org.openide.util.Lookup;
import org.xml.sax.InputSource;

public class GraphGephi {

	static Workspace workspace;
	static ImportController importController;
	static GraphModel graphModel;	
	static LinkedList<Map<String, Object>> nodes;
	
	public static LinkedList<Map<String, Object>> getNodes(String inputgraph) {
	    
		//Init a project - and therefore a workspace
	    ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
	    pc.newProject();
	    
	    //Get controllers and models
		Workspace workspace = pc.getCurrentWorkspace();
		ImportController importController = Lookup.getDefault().lookup(ImportController.class);
		GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
		AttributeModel attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel();
		
		//Import file
	    Container container;
	    try {
	        container = importController.importFile(new File(inputgraph));
	    } catch (Exception ex) {
	        ex.printStackTrace();
	        return null;
	    }

	    //Append imported data to GraphAPI
	    importController.process(container, new DefaultProcessor(), workspace);
		
		final UndirectedGraph graph = graphModel.getUndirectedGraph();
				
		Degree degree = new Degree();
		System.out.println("Calculating degrees...");			
		degree.execute(graphModel, attributeModel);
		
		/*
		GraphDistance distance = new GraphDistance();
		System.out.println("Calculating Graph Distance...");
		distance.execute(graphModel, attributeModel);		
		
		ClusteringCoefficient clustercoefficient = new ClusteringCoefficient();
		System.out.println("Calculating Clustering Coefficient");
		clustercoefficient.execute(graphModel, attributeModel);
		
		Hits hits = new Hits();
		System.out.println("Calculating HITS...");
		hits.execute(graphModel, attributeModel);
		
		PageRank pagerank = new PageRank();
		System.out.println("Calculating PageRank...");
		pagerank.execute(graphModel, attributeModel);
		
		EigenvectorCentrality eigenvectorcentrality = new EigenvectorCentrality();
		eigenvectorcentrality.execute(graphModel, attributeModel);
		*/
		
		nodes = new LinkedList<Map<String,Object>>();
		
		for (Node n : graph.getNodes()) {
			
			Attributes attr = n.getNodeData().getAttributes();
			AttributeColumn freq = attributeModel.getNodeTable().getColumn("freq");
			
			/*
			AttributeColumn deg = attributeModel.getNodeTable().getColumn(Degree.DEGREE);
			AttributeColumn pag = attributeModel.getNodeTable().getColumn(PageRank.PAGERANK);
			AttributeColumn auth = attributeModel.getNodeTable().getColumn(Hits.AUTHORITY);
			AttributeColumn hub = attributeModel.getNodeTable().getColumn(Hits.HUB);			
			AttributeColumn betweeness = attributeModel.getNodeTable().getColumn(distance.BETWEENNESS);
			AttributeColumn closseness = attributeModel.getNodeTable().getColumn(distance.CLOSENESS);
			AttributeColumn eccentricity = attributeModel.getNodeTable().getColumn(distance.ECCENTRICITY);			
			AttributeColumn clustering = attributeModel.getNodeTable().getColumn(clustercoefficient.CLUSTERING_COEFF);
			AttributeColumn eigenvector = attributeModel.getNodeTable().getColumn(eigenvectorcentrality.EIGENVECTOR);
			*/
			
			int f = (Integer) n.getNodeData().getAttributes().getValue(freq.getIndex());	// freq
			
			/*
			int d = (Integer) n.getNodeData().getAttributes().getValue(deg.getIndex());		// degree
			double p = (Double) n.getNodeData().getAttributes().getValue(pag.getIndex());	// pageRank
			float a = (Float) n.getNodeData().getAttributes().getValue(auth.getIndex());	// auth
			float h = (Float) n.getNodeData().getAttributes().getValue(hub.getIndex());		// hub
			double cc = (Double) n.getNodeData().getAttributes().getValue(clustering.getIndex());	// clustering coefficient
			double eg = (Double) n.getNodeData().getAttributes().getValue(eigenvector.getIndex());	// eigen vector centrality				
			double b = (Double) n.getNodeData().getAttributes().getValue(betweeness.getIndex());   // betweeness
			double c = (Double) n.getNodeData().getAttributes().getValue(closseness.getIndex());   // closseness
			double e = (Double) n.getNodeData().getAttributes().getValue(eccentricity.getIndex()); // eccentricity
			*/
			Map<String, Object> properties = MapUtil.map();
			
			properties.put("id", 	attr.getValue(0));
			properties.put("ename", attr.getValue(3));
			properties.put("etype", attr.getValue(2));
			properties.put("freq",  attr.getValue(4));
			
			/*
			properties.put("degree", d);
			properties.put("eccentricity", e);
			properties.put("closeness", c);
			properties.put("betweeness", b);			
			properties.put("authority", a);
			properties.put("hub", h);
			properties.put("pagerank", p);
			properties.put("cc", cc);
			properties.put("eigenvector", eg);
			 */
			nodes.add(properties);
		}
		
		return nodes;		
	}

	public static LinkedList<MyRelationship> getEdges(String inputgraph) {
		
		LinkedList<MyRelationship> edges = new LinkedList<MyRelationship>();
		
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();		
			SAXParser saxParser = factory.newSAXParser();
			
			InputStream inputStream= new FileInputStream(inputgraph);
			Reader reader = new InputStreamReader(inputStream,"UTF-8");
			InputSource is = new InputSource(reader);
			is.setEncoding("UTF-8");			
			System.out.println("Parsing " + inputgraph);			
			GraphMLParser parser = new GraphMLParser(edges);
			saxParser.parse(is, parser);
			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}		
		return edges;
	}
}

	
	
	
	
	